﻿<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
</head>
<body>
    <a href="http://javascriptissexy.com/javascript-apply-call-and-bind-methods-are-essential-for-javascript-professionals/">Aply in JS</a>

</body>
</html>
<script type="text/javascript">

    /***************************************************************************/
    //Bind () Allows us to Borrow Methods
    /***************************************************************************/
    var user = {
        // local data variable
        data: [{ name: "T. Woods", age: 37 }, { name: "P. Mickelson", age: 43 }],
        showData: function (event) {
            var randomNum = ((Math.random() * 2 | 0));
            console.log(this.data[randomNum].name + " " + this.data[randomNum].age);
        }
    };

    var cars = {
        data: [
            { name: "Honda Accord", age: 14 },
            { name: "Tesla Model S", age: 2 }
        ]
    };

    // We can borrow the showData () method from the user object we defined in the last example.
    // We bind the user.showData method to the cars object we just created.
    cars.showData = user.showData.bind(cars);
    cars.showData(); // Honda Accord 14
    user.showData();

    /***************************************************************************/
    //Function Currying, also known as partial function application, is the use of a function (that accept one or more arguments) that returns a new function with some of the arguments already set
    /***************************************************************************/
    function greet(gender, age, name) {
        // if a male, use Mr., else use Ms.
        var salutation = gender === "male" ? "Mr. " : "Ms. ";
        if (age > 25) {
            return "Hello, " + salutation + name + ".";
        }
        else {
            return "Hey, " + name + ".";
        }
    }

    // So we are passing null because we are not using the "this" keyword in our greet function.
    var greetAnAdultMale = greet.bind(null, "male", 45);
    greetAnAdultMale("John Hartlove"); // "Hello, Mr. John Hartlove."

    var greetAYoungster = greet.bind(null, "", 16);
    greetAYoungster("Alex"); // "Hey, Alex."
    greetAYoungster("Emma Waterloo"); // "Hey, Emma Waterloo."


    /***************************************************************************/
    //Set the this value with Apply or Call
    /***************************************************************************/
    // global variable for demonstration
    var avgScore = "global avgScore";

    //global function
    function avg(arrayOfScores) {
        // Add all the scores and return the total
        var sumOfScores = arrayOfScores.reduce(function (prev, cur, index, array) {
            return prev + cur;
        });

        // The "this" keyword here will be bound to the global object, unless we set the "this" with Call or Apply
        this.avgScore = sumOfScores / arrayOfScores.length;
    }

    var gameController = {
        scores: [20, 34, 55, 46, 77],
        avgScore: null
    };

    // If we execute the avg function thus, "this" inside the function is bound to the global window object:
    avg(gameController.scores);
    // Proof that the avgScore was set on the global window object
    console.log(window.avgScore); // 46.4
    console.log(gameController.avgScore); // null

    // reset the global avgScore
    avgScore = "global avgScore";
    // To set the "this" value explicitly, so that "this" is bound to the gameController,
    // We use the call () method:
    avg.call(gameController, gameController.scores);
    /*The apply and call methods are almost identical when setting the this value except that you pass the function parameters to apply () as an array, while you have to list the parameters individually to pass them to the call () method*/
    avg.apply(gameController, [gameController.scores]);

    console.log(window.avgScore); //global avgScore
    console.log(gameController.avgScore); // 46.4
</script>
